# -*- coding:utf-8 -*-
# @Time : 21-9-6 上午10:03 
# @Author : zdy
# @File : UIReport.py
# desc:
from copy import copy

from Class.Preview import Reader
from Class.Format import *
from Class.StandardMode import ResultMode
import xlsxwriter
from Class.ReportPDF import *
from Class.Log import log
from importQT import *
from Class.Devices import *
from Class.VoltSignal import dataBase
from PyQt5.QtSql import QSqlQueryModel
from Class.cs598 import *

class UIReport(QDialog, Ui_Report):
    def __init__(self):
        super(UIReport, self).__init__()
        self.ids=[]
        self.setupUi(self)
        self.setWindowFlags(Qt.WindowCloseButtonHint)
        self.setFixedSize(self.width(), self.height())
        self.setWindowTitle('报告')
        self.applyResource()
        self.setAcceptDrops(True)
        # self.treeWidget.setColumnCount(2)
        # self.treeWidget.setHeaderLabels(["时间", "样品名称"])
        # self.treeWidget.setColumnWidth(0, 200)
        # self.treeWidget.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)#设置可多选，取消的话，就再点击一次

        self.btnDelete.clicked.connect(self.btnDelete_clicked)
        self.btnNew.clicked.connect(self.btnNew_clicked)
        self.btnExcel.clicked.connect(self.btnExcel_clicked)
        self.btnpdf.clicked.connect(self.btnpdf_clicked)
        self.btnPrint.clicked.connect(self.btnPrint_clicked)

        self.position = 0  # excel要写入的行号
        self.itemModel = QStandardItemModel()
        self.itemModel.setColumnCount(2)
        self.itemModel.setRowCount(dataBase.colNum)
        self.itemModel.setHeaderData(0, Qt.Horizontal, "显示")
        self.itemModel.setHeaderData(1, Qt.Horizontal, "列项")
        # for i in range(dataBase.colNum):
        #     if i == dataBase.dbColUser[1] and deviceType == "CS":
        #         continue
        #     caption = device.modelResult.horizontalHeaderItem(i).data(0)
        #     item = QListWidgetItem()
        #     item.setData(Qt.DisplayRole, caption)
        #     item.setData(Qt.CheckStateRole, Qt.Unchecked)
        #     self.listWidget.addItem(item)

        self.btnLims.clicked.connect(self.btnLims_clicked)
        self.initchks()
        self.model =QSqlQueryModel()
        self.model.setQuery("SELECT * FROM Result")
        self.tableView.setModel(self.model)
    def initchks(self):
        self.chks = []
        # self.layout().removeItem(self.verticalLayout)
        # self.gridLayout = QtWidgets.QGridLayout(self)
        # self.layout().addLayout(self.gridLayout)
        verticalLayout = QVBoxLayout(self.listWidget)
        for i, name in enumerate(dataBase.dbColNames):
            #if name == dataBase.dbColUser[0] and deviceType == "CS":
            #    continue
            chk = QCheckBox(self)
            chk.setText(name)
            if i in device.getresultcolHidden():
                chk.setChecked(False)
            else:
                chk.setChecked(True)
            # self.gridLayout.addWidget(chk, i/2, i%2, 1, 1)
            verticalLayout.addWidget(chk)
            self.chks.append(chk)
    def btnLims_clicked(self):
        print("btnLims_clicked")
        tables = self.seperateDatas()
        if len(tables) > 0:
            path=os.path.join(os.path.expanduser('~'),"Desktop")
            filesave = path+"\\report.xlsx"#self.selectDir("Excel File", ".xlsx")
            if filesave == "":
                return
            self.position = 0
            # Create a workbook and add a worksheet.
            workbook = xlsxwriter.Workbook(
                filename=filesave,
                # options={#全局设置        #全局设置不起作用，估计是有resultformat、percentformat格式的原因
                #     'align': 'center',  # 水平位置设置：居中
                #     'valign': 'vcenter',  # 垂直位置设置，居中
                #     'text_wrap': True,#自动换行}
            )
            fontformat = {
                'align': 'center',  # 水平位置设置：居中
                'valign': 'vcenter',  # 垂直位置设置，居中
                'text_wrap': True,  # 自动换行}
            }
            worksheet = workbook.add_worksheet()
            resultformat = {'num_format': Format.result(0.0, True)}
            resultformat.update(fontformat)
            percentformat = {'num_format': Format.percent(0.0, True)}
            percentformat.update(fontformat)
            areaformat = {'num_format': Format.area(0.0)}
            areaformat.update(fontformat)
            weightformat = {'num_format': Format.weight(0.0)}
            weightformat.update(fontformat)
            # Add a number format for cells with money.
            self.excelResultformat = workbook.add_format(resultformat)
            self.excelPercentformat = workbook.add_format(percentformat)
            self.excelAreaformat = workbook.add_format(areaformat)
            self.excelWeightformat = workbook.add_format(weightformat)
            self.excelFontformat = workbook.add_format(fontformat)
            # <editor-fold desc="首行写导出的日期">
            # timeNow = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
            # worksheet.merge_range('A1:F1', timeNow)#合并单元格
            # self.position +=1
            # </editor-fold>
            worksheet.set_column('A:Y', 12)  # 设置列宽
            for table in tables:
                self.setupExcel(table, worksheet, self.currenttemplate)
            workbook.close()
            QMessageBox.information(self, "提示", "导出完毕")
        else:
            QMessageBox.information(self, "提示", "请添加报告数据")
    def applyResource(self):
        self.setWindowIcon(getIcon())

    # region 打印模板
    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        device.getresultcolHidden().clear()
        for i, chk in enumerate(self.chks):
            if chk.checkState() == Qt.Unchecked:
                device.getresultcolHidden().append(i)
        self.serializeTemplate()

    def serializeTemplate(self):
        pass
        # if len(self.reportTemplates) > 0:
        #     inPutPath = os.path.dirname(os.path.abspath(sys.argv[0]))  # 程序运行的绝对路径
        #     filepath = os.path.join(inPutPath, "reportTemplates.bin")
        #     Serialization.serializeToFile(filepath, self.reportTemplates)

    def btnSave_clicked(self):
        if self.currenttemplate.name != self.cbbName.currentText():
            self.currenttemplate = ReportTemplate()
            self.currenttemplate.name = self.cbbName.currentText()
            self.reportTemplates.insert(0, self.currenttemplate)
        self.ui2Template()
        self.updatecbbName()

    def btnDelTemplate_clicked(self):
        if len(self.reportTemplates) <= 1:
            QMessageBox.information(self, "提示","至少要保留一个模板")
            return
        self.currenttemplate = self.reportTemplates[1]
        del self.reportTemplates[0]
        self.template2UI()

    def cbbname_changed(self, i):
        if i >= 0:  # 切换
            self.currenttemplate = self.reportTemplates[i]
            del self.reportTemplates[i]
            self.reportTemplates.insert(0, self.currenttemplate)
            self.template2UI()

    def updatecbbName(self):
        self.cbbName.blockSignals(True)
        self.cbbName.clear()
        if len(self.reportTemplates) == 0:
            self.cbbName.addItem(self.currenttemplate.name)
        else:
            for i in self.reportTemplates:
                self.cbbName.addItem(i.name)
        self.cbbName.blockSignals(False)

    def template2UI(self):
        """模板参数更新到界面"""
        self.chkstati.setChecked(self.currenttemplate.bstatic)
        self.chkTitle.setChecked(self.currenttemplate.showtitle)
        self.txtTitle.setText(self.currenttemplate.title)
        self.chkLandspace.setChecked(self.currenttemplate.landspase)
        self.chkPageHeader.setChecked(self.currenttemplate.showpageHeader)
        self.txtPageHeader.setText(self.currenttemplate.pageHeader)
        self.updatecbbName()
        for i in range(self.listWidget.count()):
            if i in self.currenttemplate.resultcolShow:
                self.listWidget.item(i).setData(Qt.CheckStateRole, Qt.Checked)
            else:
                self.listWidget.item(i).setData(Qt.CheckStateRole, Qt.Unchecked)
        pass

    def ui2Template(self):
        self.currenttemplate:ReportTemplate
        self.currenttemplate.bstatic = self.chkstati.checkState() == Qt.Checked
        self.currenttemplate.showtitle = self.chkTitle.checkState() == Qt.Checked
        self.currenttemplate.landspase = self.chkLandspace.checkState() == Qt.Checked
        self.currenttemplate.title = self.txtTitle.text()
        self.currenttemplate.showpageHeader = self.chkPageHeader.isChecked()
        self.currenttemplate.pageHeader = self.txtPageHeader.text()
        self.currenttemplate.resultcolShow.clear()
        for i in range(self.listWidget.count()):
            if self.listWidget.item(i).data(Qt.CheckStateRole) == Qt.Checked:
                self.currenttemplate.resultcolShow.append(i)
    # endregion

    # region 导入数据节点
    def setDatas(self, rowIndexs):
        """根据行号，添加到打印列表，若打印列表无表格节点，则新建节点，并添加进去，若有多个节点，则添加到选中节点里"""
        count = len(rowIndexs)
        if count > 0:
            results = device.modelResult.getBaseItems(rowIndexs)
            if len(results) > 0:
                for r in results:
                    if(r.id in self.ids):
                        pass
                    else:
                        self.ids.append(r.id)
            print(self.ids)
        else:
            QMessageBox.information(self, "提醒", "请选择待添加的数据")

    def btnDelete_clicked(self):
        items = self.treeWidget.selectedItems()
        for item in items:
            self.deleteItem(item)

    def deleteItem(self, item):
        """# 删除控件树子节点/根节点"""
        try:
            parent1 = item.parent()
            parent1.removeChild(item)
        except Exception:
            # 遇到异常时删除根节点
            try:
                rootIndex = self.treeWidget.indexOfTopLevelItem(item)
                self.treeWidget.takeTopLevelItem(rootIndex)
            except Exception as ex:
                log.error("打印", ex)

    def btnNew_clicked(self):
        table = QTreeWidgetItem(self.treeWidget)
        table.setText(0, "表格")
        self.treeWidget.addTopLevelItem(table)
        self.treeWidget.expandItem(table)

    def dropEvent(self, a0: QDropEvent) -> None:
        """当拖拽操作在目标控件上被释放时，触发"""
        print("dropEvent")
        if a0.mimeData().hasText():
            dropstr = a0.mimeData().text()
            # print(dropstr)
            rowindexsstr = dropstr.split("&")
            rowIndexs = []
            for i in rowindexsstr:
                rowIndexs.append(int(i))
            self.setDatas(rowIndexs)
        pass

    def dragEnterEvent(self, a0: QDragEnterEvent) -> None:
        """拖拽操作时，进入该控件时，触发该事件，"""
        if a0.mimeData().hasText():
            a0.setAccepted(True)
            # print("准备接收drag")
        else:
            a0.setAccepted(False)
            # print("drag不匹配")
        pass

    # endregion

    def seperateDatas(self):
        tables = []
        tableCount = self.treeWidget.topLevelItemCount()
        if tableCount > 0:
            for i in range(tableCount):
                topItem = self.treeWidget.topLevelItem(i)
                childCount = topItem.childCount()
                if childCount > 0:
                    model = ResultMode()
                    for j in range(childCount):
                        str1 = str(topItem.child(j).data(0, 0))
                        for k in range(device.modelResult.rowCount()):
                            modelIndex = device.modelResult.index(k, 0)
                            id = device.modelResult.data(modelIndex)
                            if id == str1:
                                model.addRow(device.modelResult, [modelIndex])
                                break
                    tables.append(model)
        self.ui2Template()
        return tables

    def btnExcel_clicked(self):
        """获取打印列表的所有数据,分别写入excel中"""
        tables = self.seperateDatas()
        if len(tables) > 0:
            filesave = self.selectDir("Excel File", ".xlsx")
            if filesave == "":
                return
            self.position = 0
            # Create a workbook and add a worksheet.
            workbook = xlsxwriter.Workbook(
                filename=filesave,
                # options={#全局设置        #全局设置不起作用，估计是有resultformat、percentformat格式的原因
                #     'align': 'center',  # 水平位置设置：居中
                #     'valign': 'vcenter',  # 垂直位置设置，居中
                #     'text_wrap': True,#自动换行}
            )
            fontformat = {
                'align': 'center',  # 水平位置设置：居中
                'valign': 'vcenter',  # 垂直位置设置，居中
                'text_wrap': True,  # 自动换行}
            }
            worksheet = workbook.add_worksheet()
            resultformat = {'num_format': Format.result(0.0, True)}
            resultformat.update(fontformat)
            percentformat = {'num_format': Format.percent(0.0, True)}
            percentformat.update(fontformat)
            areaformat = {'num_format': Format.area(0.0)}
            areaformat.update(fontformat)
            weightformat = {'num_format': Format.weight(0.0)}
            weightformat.update(fontformat)
            # Add a number format for cells with money.
            self.excelResultformat = workbook.add_format(resultformat)
            self.excelPercentformat = workbook.add_format(percentformat)
            self.excelAreaformat = workbook.add_format(areaformat)
            self.excelWeightformat = workbook.add_format(weightformat)
            self.excelFontformat = workbook.add_format(fontformat)
            # <editor-fold desc="首行写导出的日期">
            # timeNow = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
            # worksheet.merge_range('A1:F1', timeNow)#合并单元格
            # self.position +=1
            # </editor-fold>
            worksheet.set_column('A:Y', 12)  # 设置列宽
            for table in tables:
                self.setupExcel(table, worksheet, self.currenttemplate)
            workbook.close()
            QMessageBox.information(self, "提示", "导出完毕")
        else:
            QMessageBox.information(self, "提示", "请添加报告数据")

    def setupExcel(self, dt: ResultMode, worksheet, template):
        """
        将表格根据当前行号，写入到worksheet中
        :param dt: 待写入excel一个表格的model
        :param worksheet: 待写入的excel
        :param template: 打印模板
        :return:
        """
        # <editor-fold desc="写入列头">
        colCurrent = 0  # 当前要写入的列
        for i in template.resultcolShow:
            caption = dt.horizontalHeaderItem(i).data(0)
            worksheet.write_string(self.position, colCurrent, caption, self.excelFontformat)
            colCurrent += 1
        # </editor-fold>
        self.position += 1
        statiList = []  # 保存各列数据，每一列是个list,作为这里的一个元素
        for i in range(dataBase.colNum):
            statiList.append([])
        rowCount = dt.rowCount()
        for j in range(rowCount):
            colCurrent = 0  # 当前要写入的列
            for k in template.resultcolShow:
                value = dt.item(j, k).data(0)
                if k in dataBase.colresultNum:
                    if isinstance(value, float):
                        worksheet.write_number(self.position, colCurrent, value / 100, self.excelResultformat)
                        statiList[k].append(value)
                    else:
                        worksheet.write(self.position, colCurrent, "***", self.excelFontformat)
                elif k in dataBase.colareaNum:
                    if isinstance(value, float):
                        worksheet.write_number(self.position, colCurrent, value, self.excelAreaformat)
                    else:
                        worksheet.write(self.position, colCurrent, "***", self.excelFontformat)
                elif k in dataBase.colweightNum:
                    if isinstance(value, float):
                        worksheet.write_number(self.position, colCurrent, value, self.excelWeightformat)
                    else:
                        worksheet.write(self.position, colCurrent, "***", self.excelFontformat)
                else:
                    worksheet.write(self.position, colCurrent, value, self.excelFontformat)
                colCurrent += 1
            self.position += 1
        if template.bstatic:
            worksheet.write(self.position, 0, "平均值", self.excelFontformat)
            worksheet.write(self.position + 1, 0, "SD", self.excelFontformat)
            worksheet.write(self.position + 2, 0, "RSD", self.excelFontformat)
            # 需要显示统计结果的列
            colCurrent = 0
            for col in template.resultcolShow:
                if col in dataBase.colresultNum:  # 如果该列需要统计
                    valueList = []
                    for value in statiList[col]:
                        valueList.append(float(value))
                    average = Factor.calculateAverage(valueList)
                    sd = Factor.calculateDeviation(valueList)
                    rsd = Factor.calculateRSD(sd, average)
                    if isinstance(average, float):
                        worksheet.write_number(self.position, colCurrent, average / 100, self.excelResultformat)
                    else:
                        worksheet.write(self.position, colCurrent, average, self.excelFontformat)
                    if isinstance(sd, float):
                        worksheet.write_number(self.position + 1, colCurrent, sd / 100, self.excelResultformat)
                    else:
                        worksheet.write(self.position + 1, colCurrent, sd, self.excelFontformat)
                    if isinstance(rsd, float):
                        worksheet.write_number(self.position + 2, colCurrent, rsd / 100, self.excelPercentformat)
                    else:
                        worksheet.write(self.position + 2, colCurrent, rsd, self.excelFontformat)

                colCurrent += 1
            self.position += 4

    def selectDir(self, type, format):
        """选择文件存储路径"""
        inPutPath = os.path.abspath(sys.argv[0])
        filePath = os.path.dirname(inPutPath)
        # <editor-fold desc="方案一">
        # fd = QFileDialog(self, "文件保存", filePath, type + "(*" + format + ")")
        # # fd.setFilter("Excel File(*"+type+")")
        # fd.setFileMode(QFileDialog.AnyFile)  # 用于保存对话框
        # fd.setViewMode(QFileDialog.List)  # 一般；列表样式
        # # 以下为汉化
        # fd.setLabelText(QFileDialog.FileName, "文件名")
        # fd.setLabelText(QFileDialog.FileType, "文件类型")
        # fd.setLabelText(QFileDialog.Accept, "保存")
        # fd.setLabelText(QFileDialog.Reject, "取消")
        # fd.setLabelText(QFileDialog.LookIn, "")
        # if fd.exec() == 1:  # QFileDialog.accepted 有问题？？
        #     files = fd.selectedFiles()
        #     return files[0] + format
        # else:
        #     return ""
        # </editor-fold>
        # <editor-fold desc="方案2：自带窗口无法汉化">
        fileName_choose, filetype = QFileDialog.getSaveFileName(self, "文件保存", filePath, "Excel File(*"+format+")")
        if fileName_choose == "":
            return ""
        return fileName_choose+ type
        # </editor-fold>

    # <editor-fold desc="pdf">
    def btnpdf_clicked(self):
        tables = self.seperateDatas()
        if len(tables) > 0:
            # Create a workbook and add a worksheet.
            filesave = self.selectDir("PDF", ".pdf")
            if filesave == "":
                return
            exportPDF(filesave, tables, self.currenttemplate)
            QMessageBox.information(self, "提示", "导出完毕")
        else:
            QMessageBox.information(self, "提示", "请添加报告数据")

    # </editor-fold>

    def btnPrint_clicked(self):
        """方案一：生成临时pdf文件，调用系统默认程序，打开，临时文件会在程序关闭时，自动删除
        方案二：生成临时pdf文件，编写pdf预览窗口，调用QPrinter打印pdf图片，但是QPrintDialog汉化有点问题
        方案三：使用QPrinter绘制，太麻烦
        """
        inPutPath = os.path.dirname(os.path.abspath(sys.argv[0]))  # 程序运行的绝对路径
        t = datetime.datetime.now().strftime("%d%H%M%S")
        filesave =os.path.join(inPutPath, "temp" + t + ".pdf")
        tables = self.seperateDatas()
        if len(tables) > 0:
            exportPDF(filesave, tables, self.currenttemplate)
        else:
            QMessageBox.information(self, "提示", "请添加报告数据")
            return
        # region 方案一
        # subprocess.Popen(["xdg-open", filesave])    #调用系统默认工具，打开文件
        # popen.wait() 可以阻塞主程序，但是采集也会被阻塞
        # endregion
        reader = Reader()
        reader.setAttribute(Qt.WA_DeleteOnClose)
        reader.read_book(filesave)
        reader.exec()


import sys, datetime
from ctypes import cdll

